home *** CD-ROM | disk | FTP | other *** search
- /*
- * Portions of this file Copyright (C) 1985, 1986, 1987, 1988,
- * 1990 Free Software Foundation, Inc.
- * Portions of this file Copyright (C) 1993, 1994 Marc Parmet.
- * This file is part of the Macintosh port of GNU Emacs.
- *
- * GNU Emacs is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
- #if defined(THINK_C)
- #include <MacHeaders>
- #else
- #include <Types.h>
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <Windows.h>
- #include <Resources.h>
- #endif
-
- #include <Processes.h>
- #include "sys/ioctl.h"
- #include <setjmp.h>
- #include "signal.h"
- #include "stdio.h"
- #include "termhooks.h"
- #include "config.h"
- #include "lisp.h"
- #include "dispextern.h"
-
- char *sys_siglist[] = {
- "bum signal!!",
- "aborted",
- "floating point exception",
- "illegal instruction",
- "interrupted",
- "segmentation violation",
- "terminated",
- "hangup",
- "killed",
- "alarm clock",
- "quit",
- "bad argument to system call",
- "iot instruction",
- "bus error",
- "bad argument to system call",
- "write on a pipe with no one to read it",
- "child status has changed",
- };
-
- /* Emulate as much as select as is possible under 4.1 and needed by Gnu Emacs
- * Only checks read descriptors.
- */
- /* How long to wait between checking fds in select */
- #define SELECT_PAUSE 1
- int select_alarmed;
-
- select_alarm ()
- {
- select_alarmed = 1;
- signal (SIGALRM, SIG_IGN);
- }
-
- /* Only rfds are checked. */
- int
- select (nfds, rfds, wfds, efds, timeout)
- int nfds;
- int *rfds, *wfds, *efds, *timeout;
- {
- int ravail = 0, orfds = 0, old_alarm;
- int timeoutval = timeout ? *timeout : 100000;
- int *local_timeout = &timeoutval;
- extern int kbd_count;
- extern int proc_buffered_char[];
- #ifndef subprocesses
- int process_tick = 0, update_tick = 0;
- #else
- extern int process_tick, update_tick;
- #endif
- int (*old_trap) ();
- char buf;
-
- if (rfds)
- {
- orfds = *rfds;
- *rfds = 0;
- }
- if (wfds)
- *wfds = 0;
- if (efds)
- *efds = 0;
-
- /* If we are looking only for the terminal, with no timeout,
- just read it and wait -- that's more efficient. */
- if (orfds == 1 && (!timeout || *timeout == 100000)
- && process_tick == update_tick)
- {
- if (!kbd_count)
- read_input_waiting ();
- *rfds = 1;
- return 1;
- }
-
- /* Once a second, till the timer expires, check all the flagged read
- * descriptors to see if any input is available. If there is some then
- * set the corresponding bit in the return copy of rfds.
- */
- while (1) {
- register int to_check, bit, fd;
-
- if (rfds) {
- for (to_check = nfds, bit = 1, fd = 0; --to_check >= 0; bit <<= 1, fd++) {
- if (orfds & bit) {
- int avail = 0, status = 0;
-
- if (bit == 1)
- avail = detect_input_pending (); /* Special keyboard handler */
- else
- status = ioctl (fd, FIONREAD, &avail);
- if (status >= 0 && avail > 0) {
- (*rfds) |= bit;
- ravail++;
- }
- }
- }
- }
- if (*local_timeout == 0 || ravail != 0 || process_tick != update_tick)
- break;
- old_alarm = alarm (0);
- old_trap = (int (*)()) signal (SIGALRM, select_alarm);
- select_alarmed = 0;
- alarm (SELECT_PAUSE);
- /* Wait for a SIGALRM (or maybe a SIGTINT) */
- while (select_alarmed == 0 && *local_timeout != 0 && process_tick == update_tick) {
- /* If we are interested in terminal input,
- wait by reading the terminal.
- That makes instant wakeup for terminal input at least. */
- if (orfds & 1) {
- read_input_waiting ();
- if (kbd_count)
- select_alarmed = 1;
- }
- else
- pause ();
- }
- (*local_timeout) -= SELECT_PAUSE;
- /* Reset the old alarm if there was one */
- alarm (0);
- signal (SIGALRM, old_trap);
- if (old_alarm != 0) {
- /* Reset or forge an interrupt for the original handler. */
- old_alarm -= SELECT_PAUSE;
- if (old_alarm <= 0)
- kill (getpid (), SIGALRM); /* Fake an alarm with the orig' handler */
- else
- alarm (old_alarm);
- }
- if (*local_timeout == 0) /* Stop on timer being cleared */
- break;
- }
- return ravail;
- }
-
- /* Read keyboard input into the standard buffer,
- waiting for at least one character. */
-
- read_input_waiting ()
- {
- extern int kbd_count;
- extern unsigned char kbd_buffer[];
- extern unsigned char *kbd_ptr;
- int val;
-
- val = read (fileno (stdin), kbd_buffer, 1);
-
- if (val > 0)
- {
- kbd_ptr = kbd_buffer;
- kbd_count = val;
- }
- }
-
- init_sys_modes()
- {
- }
-
- /* Get terminal size from system.
- Store number of lines into *heightp and width into *widthp.
- If zero or a negative number is stored, the value is not valid. */
- get_screen_size(int *widthp,int *heightp)
- {
- *widthp = *heightp = 0;
- }
-
- char *
- get_system_name(void)
- {
- static char s[256];
- unsigned char **t = (unsigned char **)GetResource('STR ',-16413);
- if (t == 0L) return "";
- HLock((Handle)t);
- pstrcpy(s,*t);
- HUnlock((Handle)t);
- PtoCstr(s);
- return s;
- }
-
- void
- wait_for_termination(int pid)
- {
- while (kill(pid, 0) >= 0)
- sleep(1);
- }
-
- void
- sys_suspend(void)
- {
- /* We bring the Finder to the front. */
-
- /* A bug in the process manager requires that we loop through all processes
- every time -- we can't simply return when we locate the finder. */
-
- ProcessSerialNumber psn,finder;
- ProcessInfoRec pir;
-
- psn.highLongOfPSN = 0;
- psn.lowLongOfPSN = kNoProcess;
- finder.lowLongOfPSN = kNoProcess;
- pir.processName = 0L;
- pir.processAppSpec = 0L;
-
- while (GetNextProcess(&psn) == noErr)
- if (GetProcessInformation(&psn,&pir) == noErr)
- if (pir.processType == 'FNDR' && pir.processSignature == 'MACS')
- finder = psn;
-
- if (finder.lowLongOfPSN != kNoProcess) SetFrontProcess(&finder);
- }
-